package com.gc.web.controller.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gc.business.domain.*;
import com.gc.business.service.*;
import com.gc.common.config.Global;
import com.gc.common.constant.BusinessConstants;
import com.gc.common.constant.Constants;
import com.gc.common.utils.DateUtils;
import com.gc.common.utils.GeTuiUtils;
import com.gc.common.utils.IdUtils;
import com.gc.common.utils.StringUtils;
import com.gc.framework.util.ShiroUtils;
import com.gc.framework.web.base.ApiBaseController;
import com.gc.system.domain.SysUser;
import com.gc.system.service.ISysDictDataService;
import com.gc.system.service.ISysUserService;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

/**
 * 电梯故障维修api接口层
 *
 * @author liujinteng
 * @date 2020-11-17
 */
@Slf4j
@Controller
@RequestMapping("/api/elevatorFault")
public class ApiElevatorFaultController extends ApiBaseController {

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IElevatorInfoService elevatorInfoService;

    @Autowired
    private IElevatorFaultService elevatorFaultService;

    @Autowired
    private IElevatorRepairService elevatorRepairService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private IFaultRecordService faultRecordService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private ICommunityManageService communityManageService;

    @Autowired
    private IIntegralConfigService integralConfigService;

    @Autowired
    private IIntegralDetailService integralDetailService;

    /**
     * 上报故障
     *
     * @param token
     * @param elevatorFault
     * @return
     */
    @PostMapping("/reportElevatorFault")
    @ResponseBody
    public Map<String, Object> reportElevatorFault(String token, ElevatorFault elevatorFault) {
        if (elevatorFault.getElevatorId() == null) {
            return error(Constants.UNVERIFY, "未选择电梯");
        }
        ElevatorInfo elevatorInfo = elevatorInfoService.getById(elevatorFault.getElevatorId());
        if (elevatorInfo == null) {
            return error(Constants.UNVERIFY, "电梯不存在");
        }
        SysUser sysUser = userService.selectUserById(getUserId(token));
        if (sysUser == null) {
            return error(Constants.UNVERIFY, "用户不存在");
        }

        //电梯名称
        elevatorFault.setElevatorName(elevatorInfo.getElevatorName());
        //故障单号
        elevatorFault.setFaultCode("GZ".concat(String.valueOf(IdUtils.getPrimaryKey())));
        //故障类型
        elevatorFault.setCreateBy(sysUser.getUserName());
        //上报类型
        elevatorFault.setReportType("0");//人工上报
        //上报时间
        elevatorFault.setReportTime(DateUtil.date());
        //处理状态
        elevatorFault.setDisposeState("1");

        boolean save = elevatorFaultService.save(elevatorFault);

        //故障转维修 -------------------------------------------------------------------------------------------------------------
        //处理人  ---->上报人
        elevatorFault.setDisposeMan(sysUser.getUserName());
        elevatorFault.setDisposeAvatar(sysUser.getAvatar() == null ? Global.getConfig("gc.default_avatar_url") : sysUser.getAvatar());
        elevatorFault.setFaultMessage(elevatorFault.getFaultMessage());
        //添加保存维修单
        elevatorRepairService.saveElevatorRepairByFault(elevatorFault);
        //更改小区、电梯状态
        if (elevatorInfo.equals("0")) {
            elevatorInfo.setIsFault("1");
            elevatorInfoService.saveOrUpdate(elevatorInfo);
        }
        CommunityManage communityManage = communityManageService.getById(elevatorInfo.getBelongCommunity());
        if (communityManage != null && communityManage.getIsFault().equals("0")) {
            communityManage.setIsFault("1");
            communityManageService.saveOrUpdate(communityManage);
        }
        elevatorFaultService.updateById(elevatorFault);

        if (save){
            //添加积分
            //获取上报故障积分
            String score = integralConfigService.getScoreByType(sysUser.getAttrId(),"1");
            //避免输出科学计数法并去除末尾零
            sysUser.setOwnScore(NumberUtil.add(sysUser.getOwnScore(),score).stripTrailingZeros().toPlainString());
            userService.updateUserInfo(sysUser);
            //生成积分明细
            IntegralDetail integralDetail = new IntegralDetail();
            integralDetail.setDetailTitle("上报故障");
            integralDetail.setScoreType("0");
            integralDetail.setChangeScore("+"+score);
            integralDetail.setUserId(sysUser.getUserId());
            integralDetail.setCreateBy(sysUser.getUserName());
            integralDetail.setCreateTime(DateUtil.date());
            integralDetailService.save(integralDetail);
            //发送消息
            //获取该公司的所有的维保工程师和维保经理
            List<SysUser> userList = userService.selectCompanyManagerAndEngineer(getUserId(token));
            if (CollUtil.isNotEmpty(userList)){
                for (SysUser user : userList) {
                    if (StringUtils.isNotEmpty(user.getCid())) {
                        GeTuiUtils.singlePush(user.getCid(), elevatorFault.getElevatorName(), "上报故障 " + elevatorFault.getElevatorName(), "/pages/tabbar/polling/errorList/errorList");
                    }
                }
            }
            return success();
        }else {
            return error(Constants.UNVERIFY,"上报失败");
        }
    }

    /**
     * 告警信息-故障信息列表  APP首页故障列表/故障详情页面的故障列表(该电梯数据)
     */
    @GetMapping("/elevatorFaultList")
    @ResponseBody
    public Map<String, Object> elevatorFaultList(String token,Long elevatorId, Integer pageNum, Integer pageSize) {

        SysUser user = userService.selectUserById(getUserId(token));

        Map<String, Object> map = new HashMap<>();
        startPage(pageNum, pageSize, "report_time DESC");
        ElevatorFault fault = new ElevatorFault();
        fault.setCompanyId(user.getAttrId());
        //fault.setDisposeState("1");
        if (elevatorId != null){
            fault.setElevatorId(elevatorId);
        }
        List<ElevatorFault> faultList = elevatorFaultService.selectElevatorFaultList(fault);
        if (faultList != null && faultList.size() != 0) {
            faultList.forEach(elevatorFault -> {
                if (StringUtils.isNotEmpty(elevatorFault.getFaultType())) {
                    elevatorFault.setFaultType(dictDataService.selectDictLabel(BusinessConstants.BUSINESS_FAULT_TYPE, elevatorFault.getFaultType()));
                }
                if (StringUtils.isNotEmpty(elevatorFault.getDisposeState())) {
                    elevatorFault.setDisposeState(dictDataService.selectDictLabel(BusinessConstants.BUSINESS_HANDLE_STATUS, elevatorFault.getDisposeState()));
                }
                //故障类型
                if (NumberUtil.isNumber(elevatorFault.getFaultType())) {
                    String business_fault_type = dictDataService.selectDictDataByType("business_fault_type", elevatorFault.getFaultType());
                    elevatorFault.setFaultType(business_fault_type);
                }

                //处理状态
                if (NumberUtil.isNumber(elevatorFault.getDisposeState())) {
                    String business_handle_status = dictDataService.selectDictDataByType("business_handle_status", elevatorFault.getDisposeState());
                    elevatorFault.setDisposeState(business_handle_status);
                }
            });
        }
        map.put("total", new PageInfo<>(faultList).getTotal());
        map.put("pageNum", pageNum);
        map.put("list", faultList);
        return success(map);
    }

    /**
     * 故障详情接口
     *
     * @param faultId
     * @return
     */
    @GetMapping("/queryElevatorFaultDetails")
    @ResponseBody
    public Map<String, Object> queryElevatorFaultDetails(Long faultId) {
        if (StringUtils.isNull(faultId)) {
            return error(Constants.UNVERIFY, "缺少必要ID");
        }
        ElevatorFault byId = elevatorFaultService.getById(faultId);
        if (byId.getReportType().equals("0")) {
            byId.setReportType("人工上报");
        } else if (byId.getReportType().equals("1")) {
            byId.setReportType("智能设备");
        } else if (byId.getReportType().equals("2")) {
            byId.setReportType("微信上报");
        }
        String faultType = sysDictDataService.selectDictDataByType("business_fault_type", byId.getFaultType());
        byId.setFaultType(faultType);
        return success(byId);
    }


    /**
     * 查询电梯的维修信息列表
     *
     * @param elevatorId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/selectRepairListByElevator")
    @ResponseBody
    public Map<String, Object> selectRepairListByElevator(String token,Long elevatorId, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isNull(elevatorId)) {
            return error(Constants.UNVERIFY, "缺少必要参数");
        }
        startPage(pageNum, pageSize, "create_time DESC");
        List<ElevatorRepair> list = elevatorRepairService.list(new ElevatorRepair() {{
            setElevatorId(elevatorId);
        }},null);
        //电梯维修记录列表返回电梯故障信息
        if (list != null && list.size() != 0) {
            list.forEach(elevatorRepair -> {
                LambdaQueryWrapper<ElevatorFault> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(ElevatorFault::getFaultCode, elevatorRepair.getFaultCode());
                ElevatorFault elevatorFault = elevatorFaultService.getOne(wrapper);
                if (StringUtils.isNotEmpty(elevatorFault.getFaultType())) {
                    elevatorFault.setFaultType(dictDataService.selectDictLabel(BusinessConstants.BUSINESS_FAULT_TYPE, elevatorFault.getFaultType()));
                }
                elevatorRepair.setElevatorFault(elevatorFault);
            });
        }
        map.put("pageNum", pageNum);
        map.put("total", new PageInfo<>(list).getTotal());
        map.put("list", list);
        return success(map);
    }

    /**
     * 我的维修列表接口
     *
     * @param token
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/selectMineRepair")
    @ResponseBody
    public Map<String, Object> selectMineRepair(String token, Integer pageNum, Integer pageSize) {
        startPage(pageNum, pageSize, "create_time DESC");
        //查询维修人是自己的
        List<ElevatorRepair> list = elevatorRepairService.list(new ElevatorRepair() {{
                    setRepairUserId(getUserId(token)); }},null);
        Map<String, Object> map = new HashMap<>();
        map.put("pageNum", pageNum);
        map.put("total", new PageInfo<>(list).getTotal());
        map.put("list", list);
        return success(map);
    }


    /**
     * 查询维修详情接口
     *
     * @param repairId
     * @return
     */
    @GetMapping("/selectRepairDetail")
    @ResponseBody
    public Map<String, Object> selectRepairDetail(Long repairId) {
        if (StringUtils.isNull(repairId)) {
            return error(Constants.UNVERIFY, "缺少必要参数");
        }
        ElevatorRepair byId = elevatorRepairService.getById(repairId);
        FaultRecord faultRecord = new FaultRecord();
        faultRecord.setFaultId(byId.getRepairId());
        List<FaultRecord> recordList = faultRecordService.list(faultRecord);
        for (FaultRecord record : recordList) {
            if(record.getTiringState().equals("接受任务")){
                byId.setLatitudeStart(record.getLatitude());
                byId.setLongitudeStart(record.getLongitude());
            }else if(record.getTiringState().equals("到达现场")){
                byId.setLatitudeEnd(record.getLatitude());
                byId.setLongitudeEnd(record.getLongitude());
            }
        }
        byId.setRecordList(recordList);

        //查询故障信息
        List<ElevatorFault> faultList = elevatorFaultService.list(new ElevatorFault() {{
            setFaultCode(byId.getFaultCode());
        }});
        byId.setElevatorFault(faultList.get(0));
        return success(byId);
    }

    /**
     * 分审核状态查询维修列表 -- 根据不同人物权限
     *
     * @param reviewType (1.待维修，2.待确认 ，3. 已完成)
     * @param isOverhaul 是否大修(0:是;1:否)
     * @return
     */
    @GetMapping("/selectListByStatus")
    @ResponseBody
    public Map<String, Object> selectListByStatus(Long reviewType, String isOverhaul, String token, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        if (reviewType == null){
            return error(Constants.UNVERIFY,"参数错误:reviewType为空");
        }
        List<ElevatorRepair> list = new ArrayList<>();
        List<ElevatorRepair> elevatorRepairList = new ArrayList<>();
        //所有待维修数据
        if (reviewType.intValue() == 1 ){
            list = elevatorRepairService.selectListByStatus(getUserId(token), reviewType, isOverhaul, pageNum, pageSize);
            //维修人是空和维修人是自己
            for (ElevatorRepair elevatorRepair : list) {
                if (elevatorRepair.getRepairUserId() == null) {
                    elevatorRepairList.add(elevatorRepair);
                }else if (elevatorRepair.getRepairUserId().intValue() == getUserId(token).intValue()){
                    elevatorRepairList.add(elevatorRepair);
                }
            }
            //维修经理待确认数据
        }else if (reviewType.intValue() == 2){
            list = elevatorRepairService.selectListByStatus(getUserId(token), reviewType, isOverhaul, pageNum, pageSize);
            String userRoles = userService.selectUserRole(getUserId(token));
            //判断是不是维保经理  是经理看全部待确定
            if (userRoles.contains(BusinessConstants.KEEP_MANAGER)){
                elevatorRepairList.addAll(list);
            }else{
                //自己提交的待确定
                for (ElevatorRepair elevatorRepair : list) {
                    if (elevatorRepair.getRepairUserId().intValue() == getUserId(token).intValue()){
                        elevatorRepairList.add(elevatorRepair);
                    }
                }
            }
            //已完成(维修人是自己)
        }else if (reviewType.intValue() == 3) {
            list = elevatorRepairService.selectListByStatus(getUserId(token), reviewType, isOverhaul, pageNum, pageSize);
            //维修人是自己
            for (ElevatorRepair elevatorRepair : list) {
                if (elevatorRepair.getRepairUserId().intValue() == getUserId(token).intValue()){
                    elevatorRepairList.add(elevatorRepair);
                }
            }
        }
        map.put("pageNum", pageNum);
        map.put("total", new PageInfo<>(elevatorRepairList).getTotal());
        map.put("list", elevatorRepairList);
        return success(map);
    }

    /**
     * 接受维修任务接口
     *
     * @param token
     * @param repairId
     * @return
     */
    @PostMapping("/startElevatorRepair")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> startElevatorRepair(String token, Long repairId, FaultRecord faultRecord) {
        Long userId = getUserId(token);
        if (StringUtils.isNull(repairId)) {
            return error(Constants.UNVERIFY, "缺少必要参数..");
        }

        //添加接受维修任务记录
        if (StringUtils.isNull(faultRecord.getLatitude()) || StringUtils.isNull(faultRecord.getLongitude())) {
            return error(Constants.UNVERIFY, "缺少维修人位置经纬度");
        }
        ElevatorRepair byId = elevatorRepairService.getById(repairId);
        //是否被别的工程师接取校验
        if (byId.getRepairUserId() != null && !byId.getRepairUserId().equals(userId)) {
            return error(Constants.UNVERIFY, "该维修已被其他工程师接取！");
        }


        try {
            SysUser userInfo = userService.selectUserById(userId);
            //是否已接取任务
            if (StringUtils.isNull(byId.getRepairUserId())) {
                faultRecord.setFaultId(byId.getRepairId());
                faultRecord.setTiringState("接受任务");
                faultRecord.setCreateTime(DateUtil.date());
                faultRecord.setRemark(userInfo.getUserName().concat(userInfo.getPhonenumber()).concat("已赶往救援现场！"));
                faultRecordService.save(faultRecord);
                //接受任务
                byId.setProcessState(1);
            }
            //接受维修任务相关字段
            byId.setRepairUserId(userId);
            byId.setRepairPeople(userInfo.getUserName());

        } catch (Exception e) {
            e.printStackTrace();
            return error(Constants.UNVERIFY, "服务器错误，请联系管理员！");
        }
        return success(elevatorRepairService.updateById(byId));
    }


    /**
     * 开始维修工作
     *
     * @param token
     * @param repairId
     * @param faultRecord
     * @return
     */
    @PostMapping("/marchElevatorRepair")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> marchElevatorRepair(String token, Long repairId, FaultRecord faultRecord) {
        Long userId = getUserId(token);
        if (StringUtils.isNull(repairId)) {
            return error(Constants.UNVERIFY, "缺少必要参数..");
        }
        ElevatorRepair byId = elevatorRepairService.getById(repairId);
        SysUser userInfo = userService.selectUserById(userId);
        //添加接受维修任务记录
        if (StringUtils.isNull(faultRecord.getLatitude()) || StringUtils.isNull(faultRecord.getLongitude())) {
            return error(Constants.UNVERIFY, "缺少维修人位置经纬度");
        }

        try {
            faultRecord.setFaultId(byId.getRepairId());
            faultRecord.setTiringState("到达现场");
            faultRecord.setCreateTime(DateUtil.date());
            faultRecord.setRemark(userInfo.getUserName().concat(userInfo.getPhonenumber()).concat("已到达现场！"));
            faultRecordService.save(faultRecord);

            //开始维修任务相关字段
            byId.setStartDate(DateUtil.date());
            //开始任务
            byId.setProcessState(2);
        } catch (Exception e) {
            e.printStackTrace();
            return error(Constants.UNVERIFY, "服务器错误，请联系管理员！");
        }
        return success(elevatorRepairService.updateById(byId));
    }


    /**
     * 完成维修/维修审核评价提交接口
     *
     * @param token
     * @param elevatorRepair
     * @param type           1.维修完成提交 2.经理审核
     * @return
     */
    @PostMapping("/submitElevatorRepair")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> submitElevatorRepair(String token, ElevatorRepair elevatorRepair, Integer type) {
        if (StringUtils.isNull(elevatorRepair.getRepairId())) {
            return error(Constants.UNVERIFY, "缺少必要参数..");
        }
        try {
            ElevatorRepair byId = elevatorRepairService.getById(elevatorRepair.getRepairId());
            if (type == 1) {
                SysUser userInfo = userService.selectUserById(byId.getRepairUserId());
                if (StringUtils.isEmpty(elevatorRepair.getRepairSign())) {
                    return error(Constants.UNVERIFY, "请先上传签名!");
                }
                //维修用时计算
                String repairHours = DateUtils.getDatePoor(byId.getStartDate(), DateUtil.date());
                elevatorRepair.setRepairHours(repairHours);
                elevatorRepair.setDoneStatus("0");
                elevatorRepair.setSubmitDate(DateUtil.date());

                FaultRecord faultRecord = new FaultRecord();
                faultRecord.setFaultId(byId.getRepairId());
                faultRecord.setTiringState("维修完成");
                faultRecord.setCreateTime(DateUtil.date());
                faultRecord.setRemark(userInfo.getUserName().concat(userInfo.getPhonenumber()).concat("已完成维修工作！"));
                faultRecordService.save(faultRecord);
                //维修完成
                elevatorRepair.setProcessState(3);

                //添加积分
                //获取上报故障积分
                String score = integralConfigService.getScoreByType(userInfo.getAttrId(),"3");
                //避免输出科学计数法并去除末尾零
                userInfo.setOwnScore(NumberUtil.add(userInfo.getOwnScore(),score).stripTrailingZeros().toPlainString());
                userService.updateUserInfo(userInfo);
                //生成积分明细
                IntegralDetail integralDetail = new IntegralDetail();
                integralDetail.setDetailTitle("故障维修");
                integralDetail.setScoreType("0");
                integralDetail.setChangeScore("+"+score);
                integralDetail.setUserId(userInfo.getUserId());
                integralDetail.setCreateBy(userInfo.getUserName());
                integralDetail.setCreateTime(DateUtil.date());
                integralDetailService.save(integralDetail);

            } else if (type == 2) {
                Long userId = getUserId(token);
                String userRoles = userService.selectUserRole(userId);
                if (StringUtils.isEmpty(elevatorRepair.getConfirmSign())) {
                    return error(Constants.UNVERIFY, "请先上传签名/维修图");
                }
                //判断是不是维保经理
                if (!userRoles.contains(BusinessConstants.KEEP_MANAGER)){
                    return error(Constants.UNVERIFY, "只有维保经理可以审批签字");
                }
                elevatorRepair.setConfirmPeople(userService.selectUserById(userId).getUserName());
                elevatorRepair.setDoneStatus("1");
                elevatorRepair.setConfirmDate(DateUtil.date());
            }
            //修改告警状态
            LambdaQueryWrapper<ElevatorFault> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ElevatorFault::getFaultCode, byId.getFaultCode());
            ElevatorFault fault = elevatorFaultService.getOne(wrapper);
            fault.setDisposeState("4");
            fault.setDisposeDate(new Date());//处理时间
            fault.setFaultDuration(DateUtils.getDatePoor(byId.getStartDate(), fault.getReportTime()));//处理时长
            elevatorFaultService.updateById(fault);
        } catch (Exception e) {
            e.printStackTrace();
            return error(Constants.UNVERIFY, "服务器错误，请联系管理员！");
        }
        return success(elevatorRepairService.updateById(elevatorRepair));
    }
}
